<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Tauri Updater Hidden Window</title>
    <script>
        const UPDATE_COMMANDS = {
            GET_STATUS: "GET_STATUS",
            GET_DOWNLOAD_PROGRESS: "GET_DOWNLOAD_PROGRESS",
            GET_INSTALLER_LOCATION: "GET_INSTALLER_LOCATION"
        };
        const UPDATE_EVENT = {
            STATUS: "STATUS",
            LOG_ERROR: "LOG_ERROR",
            DOWNLOAD_PROGRESS: "DOWNLOAD_PROGRESS",
            INSTALLER_LOCATION: "INSTALLER_LOCATION"
        };
        const UPDATE_STATUS = {
            STARTED: "STARTED",
            DOWNLOADING: "DOWNLOADING",
            INSTALLER_DOWNLOADED: "INSTALLER_DOWNLOADED",
            FAILED: "FAILED",
            FAILED_UNKNOWN_OS: "FAILED_UNKNOWN_OS"
        };
        let status = UPDATE_STATUS.STARTED;
        let progressPercent = 0, fileSize = 0, installerLocation;
        window.__TAURI__.event.listen("updateCommands", (receivedEvent)=> {
            console.log("Updater received Event updateCommands", receivedEvent);
            const {command, data} = receivedEvent.payload;
            if(command === UPDATE_COMMANDS.GET_STATUS){
                sendUpdateEvent(UPDATE_EVENT.STATUS, status);
            } else if(command === UPDATE_COMMANDS.GET_DOWNLOAD_PROGRESS){
                sendUpdateEvent(UPDATE_EVENT.DOWNLOAD_PROGRESS, {progressPercent, fileSize});
            } else if(command === UPDATE_COMMANDS.GET_INSTALLER_LOCATION){
                sendUpdateEvent(UPDATE_EVENT.INSTALLER_LOCATION, installerLocation);
            }
        });
        function sendUpdateEvent(eventName, data) {
            return window.__TAURI__.event.emit('updater-event', {eventName, data});
        }
        sendUpdateEvent(UPDATE_EVENT.STATUS, status);

        function getQueryStringParam(paramName) {
            const queryString = window.location.search;
            const urlParams = new URLSearchParams(queryString);
            return urlParams.get(paramName);
        }

        async function updateLinux() {
            // the actual install happens at app quit, since there is nothing to download at this stage,
            // we just return a downloaded flag so that the ui can show a dialog to the user.
            status = UPDATE_STATUS.INSTALLER_DOWNLOADED;
            installerLocation = "onlineInstaller";
            sendUpdateEvent(UPDATE_EVENT.STATUS, UPDATE_STATUS.INSTALLER_DOWNLOADED);
        }

        async function downloadUpdate() {
            const EVENT_PROGRESS= "progress:";
            const EVENT_INSTALL_PATH= "InstallerPath,";
            const downloadURL = decodeURIComponent(getQueryStringParam('downloadURL'));
            const appdataDir = await window.__TAURI__.path.appLocalDataDir();
            console.log('InstallerDownloadURL:', downloadURL);
            const argJson = JSON.stringify({downloadURL, appdataDir});
            window.__TAURI__.path.resolveResource("src-node/installer/download-file.js")
                .then(async nodeSrcPath=>{
                    // this is not supposed to work in linux.
                    const argsArray = [nodeSrcPath, argJson];
                    const command = window.__TAURI__.shell.Command.sidecar('phnode', argsArray);
                    command.on('close', data => {
                        console.log(`PhNode: command finished with code ${data.code} and signal ${data.signal}`);
                        if(data.code !== 0) {
                            status = UPDATE_STATUS.FAILED;
                            sendUpdateEvent(UPDATE_EVENT.LOG_ERROR, "Download Error: " + downloadURL);
                            sendUpdateEvent(UPDATE_EVENT.STATUS, UPDATE_STATUS.FAILED);
                            return;
                        }
                        status = UPDATE_STATUS.INSTALLER_DOWNLOADED;
                        sendUpdateEvent(UPDATE_EVENT.STATUS, UPDATE_STATUS.INSTALLER_DOWNLOADED);
                    });
                    command.on('error', error => {
                        console.error(`PhNode: command error: "${error}"`);
                        status = UPDATE_STATUS.FAILED;
                        sendUpdateEvent(UPDATE_EVENT.LOG_ERROR, "Download Error: " + downloadURL);
                        sendUpdateEvent(UPDATE_EVENT.STATUS, UPDATE_STATUS.FAILED);
                    });
                    command.stdout.on('data', line => {
                        console.log(`PhNode: ${line}`);
                        if(line.startsWith(EVENT_PROGRESS)){
                            progressPercent = parseInt(line.split(":")[1].trim());
                            fileSize = parseInt(line.split(":")[2].trim());
                            sendUpdateEvent(UPDATE_EVENT.DOWNLOAD_PROGRESS, {progressPercent, fileSize});
                        } else if(line.startsWith(EVENT_INSTALL_PATH)){
                            installerLocation = line.split(",")[1].trim();
                            console.log("Final installer location is: ", installerLocation);
                            sendUpdateEvent(UPDATE_EVENT.INSTALLER_LOCATION, installerLocation);
                        }
                    });
                    command.stderr.on('data', line => console.error(`PhNode: ${line}`));
                    command.spawn();
                });
        }

        async function update() {
            const platform = await __TAURI__.os.platform();
            if(platform === 'linux'){
                await updateLinux();
            } else if(platform === 'win32' || platform === 'darwin'){
                await downloadUpdate();
            } else {
                status = UPDATE_STATUS.FAILED_UNKNOWN_OS;
                sendUpdateEvent(UPDATE_EVENT.STATUS, UPDATE_STATUS.FAILED_UNKNOWN_OS);
            }
        }
        update();
    </script>
</head>
<body>
 Updating App... <br>
 This should be a hidden window if you are seeing this, something's broken, or you are debugging updates.
</body>
</html>
